﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml.Linq;

namespace SharePointUtilitiesForDevelopers.Actions
{
    /// <summary>
    /// A form to build the query options xml.
    /// </summary>
    public partial class BuildQueryOptionsForm : Form
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="BuildQueryOptionsForm"/> class.
        /// </summary>
        public BuildQueryOptionsForm()
        {
            InitializeComponent();
        }

        #endregion Constructors

        #region Properties
        
        /// <summary>
        /// Gets or sets the query options XML.
        /// </summary>
        /// <value>The query options XML definition.</value>
        public XElement QueryOptionsDefinition { get; set; }

        /// <summary>
        /// Gets the query options.
        /// </summary>
        /// <value>The query options.</value>
        public SharePointQueryOptions QueryOptions { get; private set; }

        #endregion Properties

        #region Helper Methods

        /// <summary>
        /// Binds the query options.
        /// </summary>
        /// <param name="queryOptionsXml">The query options XML.</param>
        private void BindQueryOptions(XElement queryOptionsXml)
        {
            // Ensure we have a query options object
            QueryOptions = queryOptionsXml != null? 
                                                      queryOptionsXml.ToSharePointQueryOptions() : 
                                                                                                     new SharePointQueryOptions();

            // Bind UI elements to the query options object
            datesInUtcCheckBox.DataBindings.Clear();
            datesInUtcCheckBox.DataBindings.Add("Checked", QueryOptions, "DateInUtc", false, DataSourceUpdateMode.OnPropertyChanged);
            includeMandatoryCheckBox.DataBindings.Clear();
            includeMandatoryCheckBox.DataBindings.Add("Checked", QueryOptions, "IncludeMandatoryColumns", false, DataSourceUpdateMode.OnPropertyChanged);
            recursiveScopeCheckBox.DataBindings.Clear();
            recursiveScopeCheckBox.DataBindings.Add("Checked", QueryOptions, "ViewAttributesScopeRecursive", false, DataSourceUpdateMode.OnPropertyChanged);
            pagingTextBox.DataBindings.Clear();
            pagingTextBox.DataBindings.Add("Text", QueryOptions, "PagingListItemCollectionPositionNext", false, DataSourceUpdateMode.OnPropertyChanged);
            folderTextBox.DataBindings.Clear();
            folderTextBox.DataBindings.Add("Text", QueryOptions, "Folder", false, DataSourceUpdateMode.OnPropertyChanged);
            meetingInstanceTextBox.DataBindings.Clear();
            var miBinding = new Binding("Text", QueryOptions, "MeetingInstanceID", true, DataSourceUpdateMode.OnPropertyChanged);
            miBinding.Format += miBinding_Format;
            miBinding.Parse += miBinding_Parse;
            meetingInstanceTextBox.DataBindings.Add(miBinding);

            // Set xml text
            queryOptionsXmlTextBox.Text = string.Empty;
            if (queryOptionsXml != null)
            {
                queryOptionsXmlTextBox.Text = queryOptionsXml.ToString();
            }

            // Hook up event handler
            QueryOptions.PropertyChanged += QueryOptions_PropertyChanged;
        }

        /// <summary>
        /// Validates the query options XML.
        /// </summary>
        private bool ValidateQueryOptionsXml()
        {
            try
            {
                // Validate the xml
                GetQueryOptionsTextAsXml();
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    this,
                    string.Format(Properties.Resources.ValidationQueryOptionsFormat, ex.Message),
                    Properties.Resources.ValidationQueryOptionsCaption,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);

            }
            return false;
        }

        /// <summary>
        /// Gets the view fields.
        /// </summary>
        /// <returns></returns>
        private XElement GetQueryOptionsTextAsXml()
        {
            if (!string.IsNullOrEmpty(queryOptionsXmlTextBox.Text))
            {
                return XElement.Parse(queryOptionsXmlTextBox.Text).ToSharePointQueryOptions().ToQueryOptionsXElement();
            }
            return null;
        }

        #endregion Helper Methods

        #region Event Handlers

        /// <summary>
        /// Handles the Load event of the BuildQueryOptionsForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BuildQueryOptionsForm_Load(object sender, EventArgs e)
        {
            BindQueryOptions(QueryOptionsDefinition);
        }


        /// <summary>
        /// Handles the Parse event of the miBinding control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.ConvertEventArgs"/> instance containing the event data.</param>
        private void miBinding_Parse(object sender, ConvertEventArgs e)
        {
            if (e.DesiredType != typeof (int))
            {
                return;
            }

            int value;
            if (int.TryParse(meetingInstanceTextBox.Text, out value))
            {
                e.Value = value;
            }
        }

        /// <summary>
        /// Handles the Format event of the miBinding control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.ConvertEventArgs"/> instance containing the event data.</param>
        private void miBinding_Format(object sender, ConvertEventArgs e)
        {
            if (e.DesiredType != typeof (string))
            {
                return;
            }

            e.Value = e.Value.ToString();
        }

        /// <summary>
        /// Handles the PropertyChanged event of the QueryOptions object.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        private void QueryOptions_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Update xml text when object changes
            queryOptionsXmlTextBox.Text = QueryOptions.ToQueryOptionsXElement().ToString();
        }

        /// <summary>
        /// Handles the Validating event of the queryOptionsXmlTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        private void queryOptionsXmlTextBox_Validating(object sender, CancelEventArgs e)
        {
            e.Cancel = !ValidateQueryOptionsXml();
        }

        /// <summary>
        /// Handles the Validated event of the queryOptionsXmlTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void queryOptionsXmlTextBox_Validated(object sender, EventArgs e)
        {
            // Re-bind
            BindQueryOptions(
                ((string) queryOptionsXmlTextBox.Text).ToQueryOptionsXElement());
        }

        /// <summary>
        /// Handles the Click event of the setDefaultButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void setDefaultButton_Click(object sender, EventArgs e)
        {
            // Re-bind to a new object
            BindQueryOptions(new SharePointQueryOptions().ToQueryOptionsXElement());
        }

        /// <summary>
        /// Handles the Click event of the okButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void okButton_Click(object sender, EventArgs e)
        {
            // Validate the XML
            if (!ValidateQueryOptionsXml())
            {
                return;
            }

            // Set the query options xml
            QueryOptionsDefinition = GetQueryOptionsTextAsXml();

            // Close the form
            DialogResult = DialogResult.OK;
            Close();
        }

        /// <summary>
        /// Handles the LinkClicked event of the helpLink control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void helpLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Help.ShowHelp(this, string.Format(Properties.Resources.HelpSearchUrl, Properties.Resources.HelpKeywordQueryOptions));
        }

        /// <summary>
        /// Handles the HelpRequested event of the BuildQueryOptionsForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="hlpevent">The <see cref="System.Windows.Forms.HelpEventArgs"/> instance containing the event data.</param>
        private void BuildQueryOptionsForm_HelpRequested(object sender, HelpEventArgs hlpevent)
        {
            Help.ShowHelp(this, string.Format(Properties.Resources.HelpSearchUrl, Properties.Resources.HelpKeywordQueryOptions));
        }

        #endregion Event Handlers
    }
}